Skip to content

R2.1.0 - #62

Open
Devasy wants to merge 3 commits into
mainfrom
r2.1.0
Open

R2.1.0#62
Devasy wants to merge 3 commits into
mainfrom
r2.1.0

Conversation

@Devasy

@Devasy Devasy commented Jul 23, 2026

Copy link
Copy Markdown
Owner

Release 2.1.0 Final PR
Add proper changelogs

Summary by CodeRabbit

  • New Features
    • Added a modern floating navigation bar with animated selection states, badges, accessibility support, and scroll-aware visibility.
    • Added consistent styled confirmation dialogs, SnackBars, and glassmorphic text fields.
    • Improved Android release builds with stronger optimization and obfuscation.
  • Bug Fixes
    • Improved Health Connect reliability with timeouts and graceful fallbacks.
    • Fixed readiness messaging when health metrics are incomplete.
    • Improved workout completion navigation and exercise reordering.
  • Tests
    • Expanded automated coverage across screens, services, storage, health data, AI features, and complete user flows.
  • Documentation
    • Updated repository links and added Android signing setup guidance.

Devasy and others added 2 commits July 23, 2026 15:58
* feat: add localized summaries, app metadata, and signing block information to F-Droid repository data

* chore: upgrade Android SDK 16→17, Java 11→17, Gradle/AGP/Kotlin toolchain

- compileSdk + targetSdk: 36 → 37 (Android 17 / API 37)
- Removed compileSdkExtension (not needed for base API 37)
- Java source/target compatibility: VERSION_11 → VERSION_17
- Kotlin jvmTarget: 11 → 17
- Gradle wrapper: 8.12 → 8.14.1
- AGP: 8.9.1 → 8.11.1
- Kotlin Gradle Plugin: 2.1.0 → 2.2.20
- Enable android.builtInKotlin=true + android.newDsl=true
- Remove explicit id(kotlin-android) plugin (now injected by Flutter)

* chore: update pubspec.lock (transitive dependency bumps)

* chore: update repo name and username references to RepForge and Devasy

* upadtes the build gradle kts file to match the review comment

* Adds pubspec yaml

---------

Co-authored-by: Devasy Patel <110348311+Devasy23@users.noreply.github.com>
* feat: add localized summaries, app metadata, and signing block information to F-Droid repository data

* chore: upgrade Android SDK 16→17, Java 11→17, Gradle/AGP/Kotlin toolchain

- compileSdk + targetSdk: 36 → 37 (Android 17 / API 37)
- Removed compileSdkExtension (not needed for base API 37)
- Java source/target compatibility: VERSION_11 → VERSION_17
- Kotlin jvmTarget: 11 → 17
- Gradle wrapper: 8.12 → 8.14.1
- AGP: 8.9.1 → 8.11.1
- Kotlin Gradle Plugin: 2.1.0 → 2.2.20
- Enable android.builtInKotlin=true + android.newDsl=true
- Remove explicit id(kotlin-android) plugin (now injected by Flutter)

* chore: update pubspec.lock (transitive dependency bumps)

* chore: update repo name and username references to RepForge and Devasy

* upadtes the build gradle kts file to match the review comment

* Adds pubspec yaml

* Enhances the bottom nav bar

* fixes out bulging issue

* Updates the bottom navbar UI, and then adds build size reuction params

* Adds build script and upgrades the release workflow

* Adds tests

* updates acc to review comments

* Adds gitignore and updates codecov yaml

* updated comments according to review comments

---------

Co-authored-by: Devasy Patel <110348311+Devasy23@users.noreply.github.com>
@Devasy Devasy self-assigned this Jul 23, 2026
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Changes

Release and platform configuration

Layer / File(s) Summary
CI and release workflow updates
.codecov.yml, .github/workflows/*, .gitignore, README.md, workout-logger/fastlane/...
CI triggers, action versions, caching, permissions, Codecov settings, signing validation, obfuscated builds, and repository references are updated.
Android toolchain and signing
workout-logger/android/*
Android now targets SDK 37 and Java/Kotlin 17. Gradle tooling, signing fallback properties, shrinking, and ProGuard rules are updated.
Project metadata and release tooling
workout-logger/pubspec.yaml, workout-logger/scripts/build_release.py
Flutter package constraints and versions are updated. A Python script builds an obfuscated ARM64 release APK with split debug information.

Application behavior and UI

Layer / File(s) Summary
Shared UI components and screen integration
workout-logger/lib/screens/widgets/floating_nav_bar.dart, rf_dialogs.dart, rf_widgets.dart, home_screen.dart, edit_workout_session_screen.dart, routine_creator.dart
Floating navigation, reusable SnackBars, confirmation dialogs, and RFTextField are added. Existing screens use the shared components.
Health handling and navigation behavior
workout-logger/lib/services/health_connect_service.dart, readiness_card.dart, health_detail_shell.dart, workout_flow_screen.dart
Health Connect operations use cached connectors and timeouts. Readiness evidence handles missing values. Workout completion replaces the current route.
Routine and import interactions
workout-logger/lib/screens/widgets/routine_creator.dart, workout-logger/lib/screens/programs/import_program_screen.dart
Routine reordering and notifications are updated. File picker configuration no longer sets an explicit single-file option.

Test infrastructure and application coverage

Layer / File(s) Summary
Test harnesses, fixtures, and service stubs
workout-logger/test/test_utils/*
Reusable providers, fixtures, interaction helpers, viewport setup, and Health Connect stubs are added.
Service, storage, and model tests
workout-logger/test/*_test.dart, workout-logger/test/services/*, workout-logger/test/storage_service_test.dart
Tests cover API behavior, logging, Gemini context, Health Connect, settings, storage, and sleep and heart-rate models.
Screen and widget tests
workout-logger/test/screens/*
Widget tests cover application screens, health components, cards, dialogs, reusable widgets, routines, targets, and workout flows.
End-to-end user-flow tests
workout-logger/test/userflow_*
User-flow suites cover AI, health, history, programs, routines, navigation, settings, targets, muscle sheets, and workout logging.

Possibly related PRs

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title identifies the release version but does not describe the main changes, such as Android upgrades, workflow updates, navigation enhancements, and expanded tests. Use a concise descriptive title that identifies the R2.1.0 release and its primary changes.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Jul 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 84.96933% with 49 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.90%. Comparing base (7834a50) to head (39fbb5e).
⚠️ Report is 5 commits behind head on main.

Files with missing lines Patch % Lines
...t-logger/lib/screens/widgets/floating_nav_bar.dart 87.68% 25 Missing ⚠️
...ut-logger/lib/services/health_connect_service.dart 44.82% 16 Missing ⚠️
...ut-logger/lib/screens/widgets/routine_creator.dart 30.00% 7 Missing ⚠️
...orkout-logger/lib/screens/workout_flow_screen.dart 0.00% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##             main      #62       +/-   ##
===========================================
+ Coverage   38.50%   74.90%   +36.40%     
===========================================
  Files          85       88        +3     
  Lines       14084    14491      +407     
===========================================
+ Hits         5423    10855     +5432     
+ Misses       8661     3636     -5025     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

* Adds tests for screens

* Adds tests

* Adds comprehensive tests

* Adds new tests

* Updates test.yml to run on release branches

* Adds test and resolved the warnings and issues

* Updates tests and minor bug fixes

* Adds fixes for failing testsm and adds connection timeout safety for health connector

* Adds missing lines patch

* Updates the tests with analyse failures

* Updates tests and routine creator to use the common component

* Updates flutter version and adds tests

---------

Co-authored-by: Devasy Patel <110348311+Devasy23@users.noreply.github.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 38

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/release.yml:
- Line 25: Pin every listed GitHub Action to a full 40-character commit SHA
instead of a mutable tag, preserving the action release name in a trailing
comment. Apply this to .github/workflows/release.yml lines 25-25, 31-31, 37-37,
and 164-164, and .github/workflows/test.yml line 29-29.
- Line 140: Update the release workflow step following the Flutter build command
to persist the generated files from build/app/outputs/symbols in protected
long-term storage before the workflow ends, alongside the existing APK artifacts
without changing the obfuscation build configuration.
- Around line 127-130: Extend the release-signing validation block in the
workflow to check KEYSTORE_BASE64, KEY_STORE_PASSWORD, KEY_ALIAS, and
KEY_PASSWORD before the build. Fail immediately with a clear configuration error
if any required secret is empty, preventing the Gradle release task from
proceeding with debug signing.

In @.github/workflows/test.yml:
- Around line 68-69: Remove the empty line immediately following the slug entry
in the workflow YAML, leaving the slug configuration and surrounding formatting
otherwise unchanged.
- Around line 42-44: Update the condition guarding the flutter pub get step to
use steps.flutter-action.outputs.PUB-CACHE-HIT rather than CACHE-HIT, so
dependency resolution runs when the project pub cache was not restored while
preserving the existing working-directory and command.

In `@workout-logger/android/app/build.gradle.kts`:
- Line 14: Align Android SDK targets with the pinned AGP 8.11.1 by changing
compileSdk and targetSdk in the Android build configuration to 36. Do not target
API 37 unless you also upgrade the AGP version in the settings plugin
declaration and the Gradle wrapper to their compatible versions.
- Around line 2-3: Update the properties-loading logic to use a scoped stream
around keyPropertiesFile.inputStream(), ensuring the stream closes after
Properties.load completes, and remove the unused FileInputStream import.
- Around line 44-48: The release signing setup around keystorePath, storePass,
alias, and keyPass must fail closed when any signing input is missing or empty,
including validating the decoded keystore file before building. Treat blank
environment variables as unavailable, require non-empty values for all four
inputs, and only allow the debug signing fallback when an explicit local-only
property is enabled; do not infer local mode from missing environment variables.

In `@workout-logger/android/gradle.properties`:
- Around line 4-7: Keep the Android toolchain consistent with the built-in
Kotlin/new DSL flags: either upgrade Flutter to 3.47+ and AGP to 9+ across
workout-logger/android/gradle.properties lines 4-7 and
workout-logger/android/app/build.gradle.kts lines 5-10 and 22-25, or disable
those flags and retain the existing legacy Kotlin Gradle Plugin configuration at
all listed sites.

In `@workout-logger/lib/screens/widgets/floating_nav_bar.dart`:
- Around line 562-580: Add a badgeColor field to FloatingNavBarTheme and update
the hasBadge indicator in the floating navigation bar to use that theme value,
falling back to cs.error when unset instead of hardcoding Colors.red. Preserve
the existing chipBg border styling.
- Around line 263-285: Update the bottom padding calculation in the floating
navigation bar to use MediaQuery.paddingOf(context) and add bottomPad to
theme.bottomMargin rather than choosing between them. Preserve the documented
padding.bottom + theme.navHeight + theme.bottomMargin spacing across devices.
- Around line 697-717: The _handleScrollNotification method currently responds
to nested and horizontal scroll updates. Restrict its ScrollUpdateNotification
handling to notifications with depth 0 and vertical axis, while preserving the
existing visibility threshold and top-of-scroll behavior for accepted
notifications.
- Around line 470-479: Update the tab widget’s Semantics/GestureDetector
interaction so it exposes an explicit onTap semantics action and supports
keyboard and switch-access focus and activation. Prefer replacing
GestureDetector with InkWell while preserving the existing haptic feedback and
widget.onTap behavior; if InkWell’s splash is unsuitable for the glassmorphic
chip, retain GestureDetector and add a Semantics onTap plus a Focus wrapper.
- Around line 725-763: Wrap the animated nav bar subtree beginning with
AnimatedSlide in Positioned(left: 0, right: 0, bottom: 0) within the Stack,
keeping the existing AnimatedSlide, AnimatedOpacity, IgnorePointer, and
FloatingNavBar behavior unchanged. This must let FloatingNavBar shrink-wrap to
the pill height so slide offsets are relative to the nav bar rather than the
full Scaffold body.

In `@workout-logger/lib/screens/widgets/rf_dialogs.dart`:
- Around line 20-41: Update the RFSnackBarType.success and RFSnackBarType.error
branches to use WCAG AA-compliant foreground/background pairs: switch success to
a dark foreground on AppColors.success, and darken the error
foreground/background combination as needed. Replace the existing inaccurate
contrast comments with comments reflecting the validated ratios, while leaving
warning and info unchanged.

In `@workout-logger/lib/screens/widgets/rf_widgets.dart`:
- Around line 904-926: Update RFTextField to use an int? maxLines while
preserving the default of 1, and add an optional FocusNode parameter. Reuse the
supplied focus node for the TextField; otherwise create and retain an internal
node, disposing it only when RFTextField created it.

In `@workout-logger/lib/screens/widgets/routine_creator.dart`:
- Around line 431-435: Update the routine save error handling around the mounted
context.showRFSnackBar call to avoid interpolating the raw exception into the
user-facing message. Log the exception with debugPrint, then show a generic
save-failure SnackBar message, matching the pattern used in
edit_workout_session_screen.dart.
- Line 147: Move the “Add Exercises” action from the item list into the
ReorderableListView.builder footer. Update itemCount to represent only
_selectedIds, remove the itemBuilder branch that renders the button at
_selectedIds.length, and adjust the reorder bounds guard to match the reduced
item range.

In `@workout-logger/lib/services/health_connect_service.dart`:
- Around line 65-73: Update _getConnector to cache the in-flight connector
creation Future so concurrent callers await the same HealthConnector.create
operation. Return the resolved connector for every caller, and clear the cached
Future only when initialization fails; preserve the existing timeout and debug
logging behavior.
- Around line 328-334: Store an hcClientRecordVersion field on WorkoutSession,
initialize it for new sessions, and increment it in
WorkoutProvider.updateWorkoutSession whenever any Health Connect-recordable
field changes. Use the current version when constructing the Health Connect
record metadata in the sync flow, while preserving hcSyncedAt solely as the
synchronization marker.

In `@workout-logger/scripts/build_release.py`:
- Around line 33-37: Update the subprocess invocation in the release-build flow
to pass the Flutter command as an argument list rather than a shell-parsed
string, and remove the shell=True usage from subprocess.run. Preserve the
existing environment and result-code propagation through sys.exit.

In `@workout-logger/test/debug_log_buffer_test.dart`:
- Around line 25-56: Update the affected tests around DebugLogBuffer.attach and
buffer.clear to store each callback passed to buffer.addListener, then remove
those same callbacks with buffer.removeListener during test cleanup. Ensure
listener cleanup runs for both tests and preserves their existing assertions.

In `@workout-logger/test/gemini_context_builder_test.dart`:
- Around line 35-86: The test exposes incorrect singular grammar in
GeminiContextBuilder.buildWeeklyInsightsContext. Update the formatter to use
“session” for a count of one and “set” for a single set, while preserving plural
forms for larger counts; then change the corresponding test expectations from “1
sessions” and “1×sets” to “1 session” and “1×set”.

In `@workout-logger/test/screens/edit_workout_session_screen_test.dart`:
- Around line 54-61: Update the add-set and delete-set assertions in the workout
session tests to require exactly one close-icon change per tap, replacing the
greater-than comparison with an assertion that the updated count equals the
initial count plus one and applying the corresponding minus-one assertion to the
delete flow.

In `@workout-logger/test/screens/heart_rate_detail_screen_test.dart`:
- Around line 18-23: Update the granularity-control assertion in the heart rate
detail screen test to require both `Day` and `Week` controls, replacing the
combined OR condition with separate expectations for each text.

In `@workout-logger/test/screens/history_screen_test.dart`:
- Around line 35-40: Replace the broad text searches in the empty-history
assertion with an exact empty-state label or dedicated widget key from the
history screen. Update the assertion around the empty-history test so it only
passes when that specific indicator is present.

In `@workout-logger/test/screens/programs/programs_screens_test.dart`:
- Around line 46-76: Strengthen the interaction tests with postcondition
assertions: in
workout-logger/test/screens/programs/programs_screens_test.dart:46-76, assert
the successful validation result after tapping Validate; in
workout-logger/test/screens/widgets/routine_creator_test.dart:26-36, require an
available exercise option and assert the selected exercise or saved routine
exists; in workout-logger/test/screens/widgets/targets_tab_test.dart:51-60,
assert a stable identifier for target_1, such as its exact exercise label or
widget key.

In `@workout-logger/test/screens/widgets/editable_exercise_card_full_test.dart`:
- Around line 21-31: Replace the consecutive DateTime.now() values in the
EditableSet fixtures within EditableExerciseCard with fixed, distinct timestamp
values, ensuring each sibling set has a unique deterministic ValueKey.
- Around line 63-68: Make both required test interactions fail when unavailable:
in workout-logger/test/screens/widgets/editable_exercise_card_full_test.dart
lines 63-68, assert the “+ Add Set” finder with findsOneWidget before tapping
it, then retain the setAdded assertion; in
workout-logger/test/screens/ai_coach_screen_full_test.dart lines 72-76,
configure input so the send control is enabled, assert the send icon exists, and
tap it without conditionally skipping the action.

In `@workout-logger/test/screens/widgets/health_cards_test.dart`:
- Around line 132-135: Update the card interaction tests around SleepHrCard and
HeartRateCard to assert their actual outcomes, not only tester.takeException().
After tapping SleepHrCard, verify its expected sheet is displayed; after tapping
HeartRateCard, verify navigation reaches the expected destination screen. Retain
the exception checks only as supplementary assertions.

In `@workout-logger/test/screens/widgets/health_widgets_test.dart`:
- Around line 74-95: Extend the HealthDetailShell test around the existing
currentG and onGranularityChanged setup to tap an alternate granularity option,
then assert that currentG changes from HealthGranularity.day to the selected
value. Keep the existing rendering and exception assertions intact.

In `@workout-logger/test/screens/widgets/workout_hr_section_test.dart`:
- Around line 75-78: Update the test around WorkoutHrSection to assert a
user-visible heart-rate statistic derived from analysis, such as the expected
average or peak BPM, in addition to verifying the widget exists. Use the test’s
existing analysis data and appropriate finder or text assertion so the test
detects missing computed values.

In `@workout-logger/test/screens/workout_flow_screen_full_test.dart`:
- Around line 44-53: Strengthen the workout-flow scenarios in
workout-logger/test/screens/workout_flow_screen_full_test.dart: lines 44-53 must
seed an exercise, require LOG SET, and verify the set was logged; lines 73-82
must likewise require and verify logging in the routine-backed flow; lines
110-118 must assert an observable deload-specific target or configuration
instead of only checking WorkoutFlowScreen visibility.

In `@workout-logger/test/services/health_connect_service_test.dart`:
- Around line 140-156: Update the test around HealthConnectService.isAvailable
to use a successful delayed platform response after 200ms and expect available
to be true, verifying the delayed success path within the deadline. If the null
response must remain, rename the test to describe unavailable-platform behavior
instead.

In `@workout-logger/test/test_utils/test_harness.dart`:
- Around line 82-86: Update the teardown callback registered by addTearDown to
be async and await tester.binding.setSurfaceSize(null), while preserving the
existing physical-size and device-pixel-ratio resets.

In `@workout-logger/test/test_utils/test_robot.dart`:
- Line 16: Update the TestRobot constructor to be const, preserving its existing
tester initialization and final-field behavior.

In `@workout-logger/test/userflow_history_and_session_details_test.dart`:
- Around line 73-75: Update the test setup around tester.view.devicePixelRatio
to register tester.view.resetDevicePixelRatio with addTearDown alongside
resetPhysicalSize, ensuring the binding restores both view properties after the
test.

In `@workout-logger/test/userflow_program_design_and_generator_test.dart`:
- Around line 55-67: Make the required UI interactions and outcome assertions
mandatory across the user-flow tests: in
workout-logger/test/userflow_program_design_and_generator_test.dart#L55-L67,
require both TextField controls and Save Program, then verify the entered
program persisted; at `#L70-L106`, load and open the program created through the
UI instead of directly saving sampleProgram; at `#L120-L135`, require the
suggestion and generate controls and assert the expected API-configuration
result. In workout-logger/test/userflow_screens_sweep_test.dart#L149-L163,
assert the required field and actions before invoking the sweep helper. In
workout-logger/test/userflow_targets_and_muscle_sheets_full_test.dart#L138-L154,
assert the required builder controls and verify a persisted or rendered result
after saving.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 20f22fbd-fd47-436c-94fe-6bbd6251f463

📥 Commits

Reviewing files that changed from the base of the PR and between 5624818 and 39fbb5e.

⛔ Files ignored due to path filters (1)
  • workout-logger/pubspec.lock is excluded by !**/*.lock
📒 Files selected for processing (77)
  • .codecov.yml
  • .github/workflows/release.yml
  • .github/workflows/test.yml
  • .gitignore
  • README.md
  • workout-logger/.gitignore
  • workout-logger/android/app/build.gradle.kts
  • workout-logger/android/app/proguard-rules.pro
  • workout-logger/android/gradle.properties
  • workout-logger/android/gradle/wrapper/gradle-wrapper.properties
  • workout-logger/android/key.properties.example
  • workout-logger/android/settings.gradle.kts
  • workout-logger/fastlane/metadata/android/en-US/full_description.txt
  • workout-logger/lib/screens/edit_workout_session_screen.dart
  • workout-logger/lib/screens/home_screen.dart
  • workout-logger/lib/screens/programs/import_program_screen.dart
  • workout-logger/lib/screens/widgets/floating_nav_bar.dart
  • workout-logger/lib/screens/widgets/health_detail_shell.dart
  • workout-logger/lib/screens/widgets/readiness_card.dart
  • workout-logger/lib/screens/widgets/rf_dialogs.dart
  • workout-logger/lib/screens/widgets/rf_widgets.dart
  • workout-logger/lib/screens/widgets/routine_creator.dart
  • workout-logger/lib/screens/workout_flow_screen.dart
  • workout-logger/lib/services/health_connect_service.dart
  • workout-logger/pubspec.yaml
  • workout-logger/scripts/build_release.py
  • workout-logger/test/api_service_test.dart
  • workout-logger/test/debug_log_buffer_test.dart
  • workout-logger/test/gemini_context_builder_test.dart
  • workout-logger/test/screens/ai_coach_screen_full_test.dart
  • workout-logger/test/screens/ai_coach_screen_test.dart
  • workout-logger/test/screens/ai_program_generator_screen_test.dart
  • workout-logger/test/screens/edit_workout_session_screen_test.dart
  • workout-logger/test/screens/heart_rate_detail_screen_test.dart
  • workout-logger/test/screens/history_screen_test.dart
  • workout-logger/test/screens/home_screen_test.dart
  • workout-logger/test/screens/onboarding_screen_test.dart
  • workout-logger/test/screens/profile_screen_full_test.dart
  • workout-logger/test/screens/profile_screen_test.dart
  • workout-logger/test/screens/programs/program_designer_screen_test.dart
  • workout-logger/test/screens/programs/programs_screens_test.dart
  • workout-logger/test/screens/settings_screen_test.dart
  • workout-logger/test/screens/sleep_detail_screen_test.dart
  • workout-logger/test/screens/widgets/editable_exercise_card_full_test.dart
  • workout-logger/test/screens/widgets/health_bar_chart_test.dart
  • workout-logger/test/screens/widgets/health_cards_test.dart
  • workout-logger/test/screens/widgets/health_widgets_test.dart
  • workout-logger/test/screens/widgets/rf_cards_test.dart
  • workout-logger/test/screens/widgets/rf_dialogs_test.dart
  • workout-logger/test/screens/widgets/rf_widgets_test.dart
  • workout-logger/test/screens/widgets/routine_creator_test.dart
  • workout-logger/test/screens/widgets/targets_tab_test.dart
  • workout-logger/test/screens/widgets/workout_hr_section_test.dart
  • workout-logger/test/screens/workout_flow_screen_full_test.dart
  • workout-logger/test/screens/workout_flow_screen_test.dart
  • workout-logger/test/services/health_connect_service_test.dart
  • workout-logger/test/settings_provider_test.dart
  • workout-logger/test/sleep_hr_builder_test.dart
  • workout-logger/test/sleep_hr_models_test.dart
  • workout-logger/test/storage_service_test.dart
  • workout-logger/test/test_utils/stub_health_connect_service.dart
  • workout-logger/test/test_utils/test_fixtures.dart
  • workout-logger/test/test_utils/test_harness.dart
  • workout-logger/test/test_utils/test_robot.dart
  • workout-logger/test/test_utils/test_sweep.dart
  • workout-logger/test/userflow_ai_coach_and_gemini_service_test.dart
  • workout-logger/test/userflow_health_and_profile_screen_test.dart
  • workout-logger/test/userflow_history_and_session_details_test.dart
  • workout-logger/test/userflow_program_design_and_generator_test.dart
  • workout-logger/test/userflow_programs_screen_deep_test.dart
  • workout-logger/test/userflow_routine_creation_test.dart
  • workout-logger/test/userflow_screens_sweep_test.dart
  • workout-logger/test/userflow_services_and_ai_sweep_test.dart
  • workout-logger/test/userflow_settings_and_storage_test.dart
  • workout-logger/test/userflow_targets_and_muscle_sheets_full_test.dart
  • workout-logger/test/userflow_targets_and_muscle_sheets_test.dart
  • workout-logger/test/userflow_workout_logging_test.dart
💤 Files with no reviewable changes (1)
  • workout-logger/lib/screens/programs/import_program_screen.dart

steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v7

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Workflow relevant lines:"
for f in .github/workflows/release.yml .github/workflows/test.yml; do
  if [ -f "$f" ]; then
    echo "--- $f"
    grep -n 'uses:\|pin|full commit|commit hash' "$f" || true
  fi
done

echo
echo "All action refs in workflows:"
python3 - <<'PY'
import pathlib, re
for p in sorted(pathlib.Path('.github/workflows').glob('*.yml')) + sorted(pathlib.Path('.github/workflows').glob('*.yaml')):
    for i,line in enumerate(p.read_text().splitlines(),1):
        m=re.search(r'uses:\s*([^#\s]+)\s*#?\s*(.*)', line.strip())
        if m:
            print(f"{p}:{i}: {m.group(1)}")
PY

Repository: Devasy/RepForge

Length of output: 1190


🌐 Web query:

GitHub Actions recommended secure workflow pinning commit SHA version tags

💡 Result:

To secure GitHub Actions workflows against supply chain attacks, GitHub and security experts strongly recommend pinning actions to a full-length (40-character) commit SHA [1][2][3][4]. Why Pinning to Commit SHAs is Necessary Standard version tags (e.g., @v4) are mutable references [3][4][5]. If an action's repository is compromised, an attacker can overwrite these tags to point to malicious code, which your workflows would then automatically execute [6][3][4][7]. Because Git tags can be moved or deleted, they do not guarantee that the code running today is the same code you audited previously [8][5][9]. A full-length commit SHA, by contrast, is a unique, immutable cryptographic digest [6][8][9]. Pinning to a specific SHA ensures your workflow always executes the exact code you intended, preventing silent, malicious updates [6][4][5][9]. Recommended Implementation To maintain both security and ease of maintenance, follow these best practices: 1. Use Full-Length SHAs: Always use the 40-character full commit SHA. Never use shortened SHAs, as they are susceptible to collision attacks [1][2][8]. 2. Keep Human-Readable References: Include the version tag as a trailing comment in your workflow file (e.g., uses: actions/checkout@a1b2c3d4e5f6... # v4.2.0) [3][4][9]. This allows automated dependency management tools like Dependabot and Renovate to detect new versions and open pull requests, ensuring you can update your actions securely while maintaining immutability [3][4][7]. 3. Enforce via Policy: If you are an administrator, you can enforce this security standard across your organization or enterprise by enabling the GitHub Actions policy that requires actions to be pinned to a full-length commit SHA [6][2][5]. When enabled, any workflow using a mutable reference (tags or branches) will fail [6][5]. Security Note: While SHA pinning prevents tag-retargeting attacks, it does not protect against code that was already malicious at the time of the initial pin [7]. Always continue to vet the actions and authors you choose to include in your pipelines [10][11].

Citations:


🌐 Web query:

actions/checkout release v5 v4 tag commit SHA

💡 Result:

In the actions/checkout repository, both v4 and v5 are major release versions [1][2]. The transition from v4 to v5 primarily involved updating the underlying Node.js runtime from Node.js 20 to Node.js 24 [3][4][5]. This update requires the use of GitHub Actions runners with version v2.327.1 or higher [5]. Regarding the use of "tag" or "commit SHA" with these versions: 1. Usage: You can reference any specific version (v4, v5, v6, v7, etc.) in your workflow file using the syntax actions/checkout@v [4][6][2]. 2. Specifying Ref/SHA: Regardless of the action version used (@v4, @v5, etc.), you can checkout a specific branch, tag, or commit SHA by using the ref input [2][7]. Example: - uses: actions/checkout@v5 with: ref: By default, the action checks out the ref or SHA that triggered the workflow [5][2]. Specifying a ref in the with block allows you to override this default behavior [2][7].

Citations:


Pin the remaining GitHub Actions to full commit hashes.

The listed mutable action tags can move or be replaced, changing pipeline behavior without a repository commit. Pin each action to a full 40-character commit SHA and keep the release name in a trailing comment.

🧰 Tools
🪛 zizmor (1.29.0)

[error] 25-25: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

📍 Affects 2 files
  • .github/workflows/release.yml#L25-L25 (this comment)
  • .github/workflows/release.yml#L31-L31
  • .github/workflows/release.yml#L37-L37
  • .github/workflows/release.yml#L164-L164
  • .github/workflows/test.yml#L29-L29
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml at line 25, Pin every listed GitHub Action to
a full 40-character commit SHA instead of a mutable tag, preserving the action
release name in a trailing comment. Apply this to .github/workflows/release.yml
lines 25-25, 31-31, 37-37, and 164-164, and .github/workflows/test.yml line
29-29.

Source: Linters/SAST tools

Comment on lines +127 to +130
if [ -z "${{ secrets.KEYSTORE_BASE64 }}" ]; then
echo "Error: KEYSTORE_BASE64 secret is not configured in repository secrets."
exit 1
fi

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Validate all release-signing secrets before the build.

Lines 127-130 validate only KEYSTORE_BASE64. The Gradle signing contract also requires KEY_STORE_PASSWORD, KEY_ALIAS, and KEY_PASSWORD. If any of these values are missing, Gradle falls back to the debug key and the workflow can publish debug-signed APKs as a release.

Proposed fix
       - name: Decode release keystore
+        env:
+          KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }}
+          KEY_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }}
+          KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
+          KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
         run: |
-          if [ -z "${{ secrets.KEYSTORE_BASE64 }}" ]; then
-            echo "Error: KEYSTORE_BASE64 secret is not configured in repository secrets."
-            exit 1
-          fi
-          echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 --decode > /tmp/repforge-release.jks
+          : "${KEYSTORE_BASE64:?KEYSTORE_BASE64 is not configured}"
+          : "${KEY_STORE_PASSWORD:?KEY_STORE_PASSWORD is not configured}"
+          : "${KEY_ALIAS:?KEY_ALIAS is not configured}"
+          : "${KEY_PASSWORD:?KEY_PASSWORD is not configured}"
+          printf '%s' "$KEYSTORE_BASE64" | base64 --decode > /tmp/repforge-release.jks
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if [ -z "${{ secrets.KEYSTORE_BASE64 }}" ]; then
echo "Error: KEYSTORE_BASE64 secret is not configured in repository secrets."
exit 1
fi
- name: Decode release keystore
env:
KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }}
KEY_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }}
KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
run: |
: "${KEYSTORE_BASE64:?KEYSTORE_BASE64 is not configured}"
: "${KEY_STORE_PASSWORD:?KEY_STORE_PASSWORD is not configured}"
: "${KEY_ALIAS:?KEY_ALIAS is not configured}"
: "${KEY_PASSWORD:?KEY_PASSWORD is not configured}"
printf '%s' "$KEYSTORE_BASE64" | base64 --decode > /tmp/repforge-release.jks
🧰 Tools
🪛 zizmor (1.29.0)

[warning] 127-127: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml around lines 127 - 130, Extend the
release-signing validation block in the workflow to check KEYSTORE_BASE64,
KEY_STORE_PASSWORD, KEY_ALIAS, and KEY_PASSWORD before the build. Fail
immediately with a clear configuration error if any required secret is empty,
preventing the Gradle release task from proceeding with debug signing.

KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
run: flutter build apk --release --split-per-abi
run: flutter build apk --release --split-per-abi --obfuscate --split-debug-info=build/app/outputs/symbols

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== files =="
git ls-files | rg '(^|/)release\.yml$|workflow|flutter|build|artifact|symbol|crash' || true

echo
echo "== release workflow around build/artifact/release =="
if [ -f .github/workflows/release.yml ]; then
  nl -ba .github/workflows/release.yml | sed -n '1,240p'
fi

echo
echo "== search for build/app/outputs/symbols and symbol upload mentions =="
rg -n "split-debug-info|build/app/outputs/symbols|flutter symbol|firebase crash|sentry|crash" .github . -g '!**/*.png' -g '!**/*.svg' || true

echo
echo "== workflow uses/references related to symbols/artifacts =="
rg -n "upload-artifact|download-artifact|split-debug-info|split-per-abi|obfuscate" . -g '*.yml' -g '*.yaml' || true

Repository: Devasy/RepForge

Length of output: 840


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== release workflow lines =="
if [ -f .github/workflows/release.yml ]; then
  awk '{printf "%6d\t%s\n", NR, $0}' .github/workflows/release.yml | sed -n '1,240p'
fi

echo
echo "== search for symbol-related references =="
rg -n "split-debug-info|build/app/outputs/symbols|flutter symbol|firebase crash|sentry|crash|upload-artifact|download-artifact|split-per-abi|obfuscate" .github workout-logger scripts . -g '*.yml' -g '*.yaml' -g '*.py' -g '*.gradle*' -g '*.dart' -g '!**/*.png' -g '!**/*.svg' || true

Repository: Devasy/RepForge

Length of output: 10250


🌐 Web query:

Flutter build apk --split-debug-info output location documentation

💡 Result:

When running a Flutter build with the --split-debug-info flag, the output location for debug symbols is determined by the directory path you explicitly provide as an argument to the flag [1][2]. The flag syntax is: flutter build --split-debug-info=/ [1][2] Key details regarding the output location: - User-Defined Path: You specify the directory path where Flutter should save the symbol files [1][2]. For example, using --split-debug-info=out/android will create a directory named out/android (relative to your project root) and place the generated symbol files there [3][2]. - Not Automatic: Flutter does not place these symbols in a default build folder unless you explicitly direct it to do so (e.g., --split-debug-info=build/app/outputs/symbols) [3]. - Purpose: This command generates symbol map files (e.g., app.android-arm.symbols), which are essential for de-obfuscating stack traces from crash reports [1][4][5]. - Persistence: It is recommended to store these symbols outside of ephemeral build directories (like the standard build/ folder), as they may be cleared by a flutter clean command [4]. Developers often commit these files to version control or an external symbol storage service to ensure they are available for future debugging sessions [4].

Citations:


Persist the obfuscation symbol files after the APK builds.

Line 140 writes split-debug-info files to build/app/outputs/symbols, but the following steps only upload and release APK files. Upload or store those symbol files in protected long-term storage before the workflow ends.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml at line 140, Update the release workflow step
following the Flutter build command to persist the generated files from
build/app/outputs/symbols in protected long-term storage before the workflow
ends, alongside the existing APK artifacts without changing the obfuscation
build configuration.

Comment on lines +42 to 44
if: steps.flutter-action.outputs.CACHE-HIT != 'true'
working-directory: ./workout-logger
run: flutter pub get

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== workflow excerpt =="
sed -n '1,140p' .github/workflows/test.yml 2>/dev/null || true

echo
echo "== related files =="
git ls-files | rg '(^|/)(pubspec\.yaml|\.dart_tool/package_config\.json|workflows/test\.yml)$' || true

echo
echo "== pubspec/package_config references =="
rg -n "pubspec|package_config|flutter pub get|CACHE-HIT|flutter-analyz|flutter test" .github workout-logger pubspec.yaml 2>/dev/null || true

echo
echo "== git status =="
git status --short

Repository: Devasy/RepForge

Length of output: 3559


🌐 Web query:

subosito flutter-action flutter analyze test cache true outputs CACHE-HIT

💡 Result:

The subosito/flutter-action GitHub Action provides CACHE-HIT and PUB-CACHE-HIT outputs that allow you to determine whether the Flutter SDK or pub dependencies were successfully retrieved from the cache [1][2][3]. These outputs are available starting from version v2.21.0 [2]. They directly reflect the cache-hit output from the underlying actions/cache steps [4][5][3]. Key details regarding these outputs: - CACHE-HIT: Indicates whether the Flutter SDK cache was a hit [1][3]. - PUB-CACHE-HIT: Indicates whether the pub dependencies cache was a hit [1][3]. - Behavior: These outputs return 'true' if there is an exact match for the cache key, and an empty string if there is a cache miss [4][6][5]. Example usage: You can use these outputs to conditionally execute steps in your workflow, such as skipping dependency installation when a cache hit occurs [7][3]: steps: - name: Set up Flutter uses: subosito/flutter-action@v2 id: flutter-action with: channel: stable cache: true - name: Conditionally run dependencies installation if: steps.flutter-action.outputs.PUB-CACHE-HIT!= 'true' run: flutter pub get - name: Continue with build run: flutter build apk Note that you must provide an id to the flutter-action step (e.g., id: flutter-action) to reference these outputs in subsequent steps [7][3].

Citations:


🌐 Web query:

site:github.com/subosito/flutter-action action.yaml CACHE-HIT PUB-CACHE-HIT cache

💡 Result:

In the context of the subosito/flutter-action GitHub Action, CACHE-HIT and PUB-CACHE-HIT are output variables that provide information about the status of the Flutter SDK and Dart pub dependencies caches, respectively [1][2]. These outputs are defined in the action's configuration (action.yaml) to allow users to conditionally execute steps based on whether a cache was restored successfully [1][2]. Specifically: CACHE-HIT: Indicates whether the Flutter SDK cache was a hit (returns 'true' if there is an exact match for the cache key) [1]. PUB-CACHE-HIT: Indicates whether the Dart pub dependencies cache was a hit (returns 'true' if there is an exact match for the cache key) [1]. These values are sourced directly from the cache-hit output of the underlying actions/cache step used within the action [3][4]. They are commonly used in workflow YAML files to skip redundant installation or setup steps, such as bootstrapping dependencies, when a valid cache already exists [2][5]. Example usage in a workflow: - name: Set up Flutter uses: subosito/flutter-action@v2 id: flutter-action with: cache: true pub-cache: true - name: Conditionally run setup if: steps.flutter-action.outputs.PUB-CACHE-HIT!= 'true' run: dart pub get

Citations:


🌐 Web query:

site:docs.dart.dev packages flutter test analyze package_config.json pub cache

💡 Result:

Relevant official Dart/Flutter documentation:

  • Packages: use pubspec.yaml and dart pub get to resolve dependencies. [1]
  • Flutter package commands: use flutter pub, flutter analyze, and flutter test; Flutter recommends these instead of the equivalent Dart commands in Flutter projects. [2]
  • Static analysis: dart analyze [DIRECTORY|FILE] analyzes Dart source code. [3]
  • Testing: Flutter tests typically live under test/; run them with flutter test. [4]
  • package_config.json: Pub generates .dart_tool/package_config.json, mapping package names to their locations; workspaces use one shared file. [5]
  • Pub cache: recent Dart versions include dart pub cache gc to remove packages no longer referenced by current projects. [6]

The original query returned no exact docs.dart.dev match; current documentation is primarily on dart.dev and docs.flutter.dev.


Run dependency resolution when the Flutter SDK cache hits.

CACHE-HIT reports whether the Flutter SDK cache was restored. This skips flutter pub get even when the project pub cache was not restored, leaving .dart_tool/package_config.json unresolved for flutter analyze and flutter test. Check steps.flutter-action.outputs.PUB-CACHE-HIT instead, or always run flutter pub get for clean runners.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/test.yml around lines 42 - 44, Update the condition
guarding the flutter pub get step to use
steps.flutter-action.outputs.PUB-CACHE-HIT rather than CACHE-HIT, so dependency
resolution runs when the project pub cache was not restored while preserving the
existing working-directory and command.

Comment on lines +68 to +69
slug: Devasy/RepForge

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove the added empty line.

The configured YAML linter rejects the empty line after slug.

🧰 Tools
🪛 YAMLlint (1.37.1)

[error] 69-69: too many blank lines (1 > 0)

(empty-lines)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/test.yml around lines 68 - 69, Remove the empty line
immediately following the slug entry in the workflow YAML, leaving the slug
configuration and surrounding formatting otherwise unchanged.

Source: Linters/SAST tools

Comment on lines +140 to +156
test('HealthConnectService succeeds when platform response takes > 100ms within deadline', () async {
const channel = 'dev.flutter.pigeon.health_connector_hc_android.HealthConnectorHCAndroidApi.getHealthPlatformStatus';
addTearDown(() {
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMessageHandler(channel, null);
});

TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMessageHandler(
channel,
(ByteData? message) async {
await Future.delayed(const Duration(milliseconds: 200));
return null;
},
);

final service = HealthConnectService();
final available = await service.isAvailable();
expect(available, isFalse);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Test the delayed success path or rename this test.

The handler returns null, and Line 156 expects false. This test does not verify that a delayed successful platform response completes within the deadline. An implementation that always returns false passes this test.

Configure a successful platform response and expect true. If failure is the intended case, rename the test to describe unavailable-platform behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@workout-logger/test/services/health_connect_service_test.dart` around lines
140 - 156, Update the test around HealthConnectService.isAvailable to use a
successful delayed platform response after 200ms and expect available to be
true, verifying the delayed success path within the deadline. If the null
response must remain, rename the test to describe unavailable-platform behavior
instead.

Comment on lines +82 to +86
addTearDown(() {
tester.view.resetPhysicalSize();
tester.view.resetDevicePixelRatio();
tester.binding.setSurfaceSize(null);
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect all test surface-size setup and teardown calls.
rg -n -C 3 'setSurfaceSize\(|addTearDown\(' workout-logger/test

Repository: Devasy/RepForge

Length of output: 3600


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate flutter test harness source to inspect setSurfaceSize contract and widget tester method signatures.
rg -n "Future<void>\s+setSurfaceSize|setSurfaceSize\(" --glob '*flutter*' --glob '*test*' /tmp 2>/dev/null || true
python3 - <<'PY'
import subprocess, sys, re, pathlib
try:
    out=subprocess.check_output(["dart", "--version"], text=True, stderr=subprocess.STDOUT)
    print("dart_version", out.strip())
except Exception as e:
    print("dart_unavailable", repr(e))
try:
    out=subprocess.check_output(["flutter", "--version"], text=True, stderr=subprocess.STDOUT)
    print("flutter_version", out.strip())
except Exception as e:
    print("flutter_unavailable", repr(e))
PY

# Inspect TestHarness implementation around prepareTester and any docs.
nl -ba workout-logger/test/test_utils/test_harness.dart | sed -n '1,120p'

Repository: Devasy/RepForge

Length of output: 331


🌐 Web query:

Flutter WidgetTester binding setSurfaceSize Future<void> await signature

💡 Result:

The setSurfaceSize method is a member of the TestWidgetsFlutterBinding class in the flutter_test library [1][2]. Its signature is as follows: Future setSurfaceSize(Size? size) [1][3] This method artificially changes the logical size of the WidgetTester.view to the specified size and flushes microtasks [1][2]. Because it returns a Future, it must be awaited when called within a test [1][3]. Key usage and implementation details include: * Awaiting the call: You should use the await keyword when calling setSurfaceSize to ensure the size change and subsequent microtask flushes are completed before proceeding with the test [1][3]. * State Management: This method affects the state of the WidgetTester.view and can leak across tests if not properly reset [1][3]. It is standard practice to reset the surface size to null (the default) after the test using addTearDown [1][3]. * Example: await binding.setSurfaceSize(someSize); addTearDown( => binding.setSurfaceSize(null)); * Deprecation Warning: Official documentation and framework source code suggest that setSurfaceSize is considered for deprecation [1][4]. It is recommended to consider using TestFlutterView.physicalSize instead, which is a more modern and flexible way to manage view configurations for any view, including the WidgetTester.view [1][3]. Top results: [1], [3], [4]

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

cat -n workout-logger/test/test_utils/test_harness.dart | sed -n '68,90p'

Repository: Devasy/RepForge

Length of output: 878


Await the setSurfaceSize(null) reset in teardown.

tester.binding.setSurfaceSize returns a Future<void>, and the setup awaits it; call addTearDown with an async callback and await the same reset to keep the fixture restoration consistent.

Proposed fix
-    addTearDown(() {
+    addTearDown(() async {
       tester.view.resetPhysicalSize();
       tester.view.resetDevicePixelRatio();
-      tester.binding.setSurfaceSize(null);
+      await tester.binding.setSurfaceSize(null);
     });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
addTearDown(() {
tester.view.resetPhysicalSize();
tester.view.resetDevicePixelRatio();
tester.binding.setSurfaceSize(null);
});
addTearDown(() async {
tester.view.resetPhysicalSize();
tester.view.resetDevicePixelRatio();
await tester.binding.setSurfaceSize(null);
});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@workout-logger/test/test_utils/test_harness.dart` around lines 82 - 86,
Update the teardown callback registered by addTearDown to be async and await
tester.binding.setSurfaceSize(null), while preserving the existing physical-size
and device-pixel-ratio resets.

class TestRobot {
final WidgetTester tester;

TestRobot(this.tester);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Make the TestRobot constructor const.

The constructor only initializes a final field. Add const to satisfy the Dart constructor guideline.

As per coding guidelines, use const constructors wherever possible.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@workout-logger/test/test_utils/test_robot.dart` at line 16, Update the
TestRobot constructor to be const, preserving its existing tester initialization
and final-field behavior.

Source: Coding guidelines

Comment on lines +73 to +75
tester.view.physicalSize = const Size(800, 1800);
tester.view.devicePixelRatio = 1.0;
addTearDown(tester.view.resetPhysicalSize);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Files matching target:"
fd -a 'userflow_history_and_session_details_test.dart' . || true

file="$(fd 'userflow_history_and_session_details_test.dart' . | head -n1 || true)"
if [ -n "$file" ]; then
  echo "\nTarget file: $file"
  wc -l "$file"
  echo "\nRelevant lines:"
  cat -n "$file" | sed -n '1,140p'
fi

echo "\nSearch reset device pixel ratio usages:"
rg -n "resetDevicePixelRatio|devicePixelRatio\\s*=|physicalSize\\s*=|resetPhysicalSize" workout-logger/test || true

Repository: Devasy/RepForge

Length of output: 6400


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "history_screen_test.dart relevant setup section:"
cat -n workout-logger/test/screens/history_screen_test.dart | sed -n '1,180p'

echo "\nDart Flutter View reset API availability in installed flutter_test source:"
flutter --version 2>/dev/null || true
for root in "$HOME/flutter/bin/cache/pkg/flutter_test/lib" "/opt/flutter/bin/cache/pkg/flutter_test/lib"; do
  [ -d "$root/src/dart_test" ] && find "$root/src/dart_test" -type f \( -name '*view*.dart' -o -name '*binding*.dart' \) -print | sort
done

echo "\nSearch package source for View.resetDevicePixelRatio:"
find "$PWD" -path '*flutter_test*' -maxdepth 8 -type f -name '*.dart' -print 2>/dev/null | xargs rg -n "resetDevicePixelRatio|class View|devicePixelRatio" 2>/dev/null || true

# Determine current binding type by source presence only.
python3 - <<'PY'
from pathlib import Path
roots=["src/flutter_test","test/flutter_test"]
for r in roots:
    if (Path(r)).exists():
        print(f"FOUND_PREFIX {r}")
PY

Repository: Devasy/RepForge

Length of output: 3951


Reset the test view device pixel ratio.

This helper changes tester.view.devicePixelRatio but only adds teardown for physical size, so tests run in the same binding can inherit 1.0. Add teardown for tester.view.resetDevicePixelRatio.

Proposed fix
       tester.view.physicalSize = const Size(800, 1800);
       tester.view.devicePixelRatio = 1.0;
       addTearDown(tester.view.resetPhysicalSize);
+      addTearDown(tester.view.resetDevicePixelRatio);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
tester.view.physicalSize = const Size(800, 1800);
tester.view.devicePixelRatio = 1.0;
addTearDown(tester.view.resetPhysicalSize);
tester.view.physicalSize = const Size(800, 1800);
tester.view.devicePixelRatio = 1.0;
addTearDown(tester.view.resetPhysicalSize);
addTearDown(tester.view.resetDevicePixelRatio);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@workout-logger/test/userflow_history_and_session_details_test.dart` around
lines 73 - 75, Update the test setup around tester.view.devicePixelRatio to
register tester.view.resetDevicePixelRatio with addTearDown alongside
resetPhysicalSize, ensuring the binding restores both view properties after the
test.

Comment on lines +55 to +67
final textFields = find.byType(TextField);
if (textFields.evaluate().length >= 2) {
await tester.enterText(textFields.at(0), 'Strength Block 1');
await tester.enterText(textFields.at(1), '4-week progressive overload');
await tester.pumpAndSettle();
}

// Tap Save Program button
final saveBtn = find.text('Save Program');
if (saveBtn.evaluate().isNotEmpty) {
await tester.tap(saveBtn);
await tester.pumpAndSettle();
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Make required UI actions mandatory in these user-flow tests.

Each listed test can pass when required controls are missing because it skips interactions when a finder is empty. The designer test then saves sampleProgram directly, so it does not verify that the UI save action persisted the entered program.

  • workout-logger/test/userflow_program_design_and_generator_test.dart#L55-L67: require the fields and Save Program, then assert that the entered program was persisted.
  • workout-logger/test/userflow_program_design_and_generator_test.dart#L70-L106: load and open the program created by the UI instead of saving sampleProgram directly.
  • workout-logger/test/userflow_program_design_and_generator_test.dart#L120-L135: require the suggestion and generate action, then assert the expected API-configuration result.
  • workout-logger/test/userflow_screens_sweep_test.dart#L149-L163: assert the required field and actions before invoking the sweep helper.
  • workout-logger/test/userflow_targets_and_muscle_sheets_full_test.dart#L138-L154: assert required builder controls and a persisted or rendered result after saving.
📍 Affects 3 files
  • workout-logger/test/userflow_program_design_and_generator_test.dart#L55-L67 (this comment)
  • workout-logger/test/userflow_program_design_and_generator_test.dart#L70-L106
  • workout-logger/test/userflow_program_design_and_generator_test.dart#L120-L135
  • workout-logger/test/userflow_screens_sweep_test.dart#L149-L163
  • workout-logger/test/userflow_targets_and_muscle_sheets_full_test.dart#L138-L154
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@workout-logger/test/userflow_program_design_and_generator_test.dart` around
lines 55 - 67, Make the required UI interactions and outcome assertions
mandatory across the user-flow tests: in
workout-logger/test/userflow_program_design_and_generator_test.dart#L55-L67,
require both TextField controls and Save Program, then verify the entered
program persisted; at `#L70-L106`, load and open the program created through the
UI instead of directly saving sampleProgram; at `#L120-L135`, require the
suggestion and generate controls and assert the expected API-configuration
result. In workout-logger/test/userflow_screens_sweep_test.dart#L149-L163,
assert the required field and actions before invoking the sweep helper. In
workout-logger/test/userflow_targets_and_muscle_sheets_full_test.dart#L138-L154,
assert the required builder controls and verify a persisted or rendered result
after saving.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant